package com.sxbbc.api.controller;

import java.util.*;

import com.sxbbc.common.basics.utils.statics.EnumUtils;
import com.sxbbc.common.core.dto.jz.*;
import com.sxbbc.common.core.enums.OfflineOrderStatusEnums;
import com.sxbbc.common.core.enums.OrderTypeEnums;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.function.common.GetRest;
import com.function.common.RestResponse;
import com.sxbbc.api.common.OrderMapping;
import com.sxbbc.api.service.IBusinessService;
import com.sxbbc.api.service.IOrderService;
import com.sxbbc.common.basics.exp.ExpDetailVo;
import com.sxbbc.common.basics.utils.calculation.CalcuUtils;
import com.sxbbc.common.basics.utils.statics.StaticUtils;
import com.sxbbc.common.core.entity.jz.OrderExpDetail;
import com.sxbbc.common.core.entity.jz.OrderMain;
import com.sxbbc.common.core.entity.jz.OrderRefundLog;
import com.sxbbc.common.core.entity.jz.ProSkuDetail;
import com.sxbbc.common.core.enums.ReceivedTypeEnums;
import com.sxbbc.common.core.service.IOrderExpDetailService;
import com.sxbbc.common.core.service.IOrderMainService;
import com.sxbbc.common.core.service.IOrderRefundLogService;
import com.sxbbc.common.core.service.IProSkuDetailService;
import com.sxbbc.common.core.service.system.login.LoginTokenService;
import com.sxbbc.common.core.service.system.pay.PayOrderService;
import com.sxbbc.common.core.service.system.redis.listener.OrderListerService;
import com.sxbbc.common.core.utils.BasePage;

/**
 * 订单控制层
 *
 * @author xiaoky
 * @date 2019-05-17
 */
@RestController

public class OrderController {
    @Autowired
    private LoginTokenService loginTokenService;
    @Autowired
    private IOrderMainService orderMainService;
    @Autowired
    private IOrderExpDetailService orderExpDetailService;
    @Autowired
    private IOrderRefundLogService orderRefundLogService;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private PayOrderService payOrderService;
    @Autowired
    private IProSkuDetailService proSkuDetailService;
    @Autowired
    private IBusinessService apiBusinessService;
    @Autowired
    private OrderListerService orderListerService;


    //region 线下订单

    /**
     * 核销线下订单
     *
     * @param token
     * @param code
     * @return
     */
    @RequestMapping(value = OrderMapping.HANDLE_OFFLINE_ORDER_CODE)
    public RestResponse getOfflineOrderTab(String token, String code) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        QueryWrapper<OrderMain> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("code", code).eq("cid", cid);
        OrderMain orderMain = orderMainService.getOne(queryWrapper);
        if (orderMain != null) {
            if (CalcuUtils.getInstance().isEquals(orderMain.getOrderStatus(), OfflineOrderStatusEnums.WAIT_USED.getId())) {
                orderMain.setOrderStatus(OfflineOrderStatusEnums.COMPLETE.getId());
                orderMain.setOverTime(new Date());
                orderMainService.updateById(orderMain);
                //TODO 后期需要写模式


            } else {
                return GetRest.getFail("该订单无法进行核销");
            }

        }
        return GetRest.getSuccess("操作成功");
    }

    /**
     * 查询线下订单核销码信息
     *
     * @param token
     * @param id
     * @return
     */
    @RequestMapping(value = OrderMapping.GET_OFFLINE_ORDER_CODE)
    public RestResponse getOfflineOrderCode(String token, Integer id) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        OrderMain orderMain = orderMainService.getById(id);
        orderMain.setOrderStatusName(EnumUtils.getEnum(OfflineOrderStatusEnums.class, EnumUtils.GET_ID, orderMain.getOrderStatus()).getName());
        OfflineOrderCodeVo vo = new OfflineOrderCodeVo();
        BeanUtils.copyProperties(orderMain, vo);
        return GetRest.getSuccess("操作成功", vo);
    }

    /**
     * 查询线下订单列表
     *
     * @param orderMain 订单查询数据
     * @param token     获取cid
     * @return 订单列表数据
     */
    @RequestMapping(value = OrderMapping.QUERY_OFFLINE_ORDER_LIST)
    public RestResponse queryOfflineOrderList(BasePage<OrderMain> page, OrderMain orderMain, String token) {
        // 查询未删除的订单
        orderMain.setDel(StaticUtils.STATUS_NO);
        // 获取cid
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        orderMain.setCid(cid);
        orderMain.setOrderType(OrderTypeEnums.OFFLINE.getId());
        IPage<OrderBaseVo> pageInfo = orderService.queryOrder(page, orderMain);
        return GetRest.getSuccess("", pageInfo);
    }

    /**
     * 查询线下订单核销信息
     * @param id
     * @param token
     * @return
     */
    @RequestMapping(value = OrderMapping.QUERY_OFFLINE_ORDER_VERIFY)
    public RestResponse queryOfflineOrderVerify(Integer id, String token) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        OrderMain orderMain = orderMainService.getById(id);
        orderMain.setOrderStatusName(OfflineOrderStatusEnums.getName(orderMain.getOrderStatus()));
        return GetRest.getSuccess("", orderMain);
    }

    //endregion

    //region 商城订单

    /**
     * 获取商城订单角标
     *
     * @param token 获取cid
     * @return Map 订单角标数据
     */
    @RequestMapping(value = OrderMapping.GET_ORDER_TAB)
    public RestResponse getOrderTab(String token) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        OrderMain orderMain = new OrderMain();
        orderMain.setCid(cid);
        orderMain.setOrderType(OrderTypeEnums.NORMAL.getId());
        Map<String, Integer> map = orderMainService.getOrderNum(orderMain);
        return GetRest.getSuccess("", map);
    }

    /**
     * 查询订单列表
     *
     * @param orderMain 订单查询数据
     * @param token     获取cid
     * @return 订单列表数据
     */
    @RequestMapping(value = OrderMapping.QUERY_ORDER_LIST)
    public RestResponse queryOrderList(BasePage<OrderMain> page, OrderMain orderMain, String token) {
        // 查询未删除的订单
        orderMain.setDel(StaticUtils.STATUS_NO);
        // 查询未全部退款的订单
        orderMain.setQueryRefund(StaticUtils.STATUS_NO);
        // 获取cid
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        orderMain.setCid(cid);
        orderMain.setOrderType(OrderTypeEnums.NORMAL.getId());
        IPage<OrderBaseVo> pageInfo = orderService.queryOrder(page, orderMain);
        return GetRest.getSuccess("", pageInfo);
    }

    /**
     * 查询订单详情
     *
     * @param token     获取cid
     * @param orderCode 订单编号
     * @return 订单详情数据
     */
    @RequestMapping(value = OrderMapping.GET_ORDER_DETAIL)
    public RestResponse getOrderDetail(String token, String orderCode) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        OrderMain order = orderMainService.getByOrderCode(orderCode);
        if (!CalcuUtils.getInstance().isEquals(cid, order.getCid())) {
            return GetRest.getFail("订单数据有误");
        }
        OrderDetailVo result = orderService.handleQueryOrderDetailById(order.getId());
        return GetRest.getSuccess("", result);
    }

    /**
     * 删除订单——逻辑假删除
     *
     * @param token     获取cid
     * @param orderCode 订单编号
     * @return RestResponse 处理结果
     */
    @RequestMapping(value = OrderMapping.DELETE_ORDER)
    public RestResponse deleteOrder(String token, String orderCode) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        RestResponse result = orderService.deleteOrder(cid, orderCode);
        return result;
    }

    /**
     * 取消订单
     *
     * @param token        获取cid
     * @param orderCode    订单编号
     * @param cancelReason 取消原因
     * @return RestResponse 处理结果
     */
    @RequestMapping(value = OrderMapping.CANCEL_ORDER)
    public RestResponse cancelOrder(String token, String orderCode, String cancelReason) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        orderListerService.handleOrderTimeout(orderCode);
        return GetRest.getSuccess("取消成功");
    }

    /**
     * 提醒商家发货
     *
     * @param token     获取cid
     * @param orderCode 订单编号
     * @return RestResponse 处理结果
     */
    @RequestMapping(value = OrderMapping.HANDLE_ORDER_REMIND)
    public RestResponse handleOrderRemind(String token, String orderCode) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        RestResponse result = orderService.handleOrderRemind(cid, orderCode);
        return result;
    }

    /**
     * 订单确认收货
     *
     * @param token     获取cid
     * @param orderCode 订单编号
     * @return RestResponse 处理结果
     */
    @RequestMapping(value = OrderMapping.HANDLE_ORDER_RECEIVE)
    public RestResponse handleOrderReceive(String token, String orderCode) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        OrderMain order = orderMainService.getByOrderCode(orderCode);
        if (!CalcuUtils.getInstance().isEquals(cid, order.getCid())) {
            return GetRest.getFail("订单数据有误");
        }
        RestResponse result = orderService.handleOrderReceive(cid, orderCode);
        return result;
    }

    /**
     * 获取订单物流详情
     *
     * @param token     获取cid
     * @param orderCode 订单编号
     * @return RestResponse 物流详情
     */
    @RequestMapping(value = OrderMapping.GET_ORDER_EXP_DETAIL)
    public RestResponse getOrderExpDetail(String token, String orderCode, Integer expId) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        OrderMain order = orderMainService.getByOrderCode(orderCode);
        if (!CalcuUtils.getInstance().isEquals(cid, order.getCid())) {
            return GetRest.getFail("订单数据有误");
        }
        OrderExpDetail expDetail = orderExpDetailService.getById(expId);
        if (expDetail != null && CalcuUtils.getInstance().isEquals(expDetail.getReceivedType(), ReceivedTypeEnums.EXP.getId())) {
            String expMsg = orderExpDetailService.handleLiveExpData(expDetail.getId());
            List<ExpDetailVo> expMsgList = JSONArray.parseArray(expMsg, ExpDetailVo.class);
            if (expMsgList != null && expMsgList.size() > 0) {
                Collections.reverse(expMsgList);
            }
            expDetail.setExpDetailList(expMsgList);
        }
        return GetRest.getSuccess("", expDetail);
    }

    /**
     * 订单评论接口
     *
     * @param token 获取cid
     * @return 评论结果
     */
    @RequestMapping(value = OrderMapping.HANDLE_ORDER_EVALUATE)
    public RestResponse handleOrderEvaluate(String token, OrderEvaluateVo vo) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        RestResponse result = orderService.handleOrderEvaluate(cid, vo);
        return result;
    }

    //endregion

    //region 订单支付数据显示

    /**
     * 获取单笔支付信息
     *
     * @param token     用户token
     * @param addrId    收货地址id
     * @param proCode   产品编号
     * @param qty       数量
     * @param orderType 交易类型 1普通  3拼团
     * @param groupCode 加入团购编号
     * @return 返回 status 状态，data数据结构，flag交易单号
     */
    @RequestMapping(value = OrderMapping.GET_SINGLE_ORDER)
    public RestResponse getSingleOrder(String token, Integer addrId, String proCode, String sku, Integer qty, Integer orderType, String groupCode) {
        Integer skuId = null;
        //获取商品详情
        ProSkuDetail skuDetail = new ProSkuDetail();
        if (StringUtils.isNotBlank(sku)) {
            QueryWrapper<ProSkuDetail> wrapper = new QueryWrapper<>();
            wrapper.eq("pro_code", proCode).eq("spec_name", sku);
            skuDetail = proSkuDetailService.getOne(wrapper);
        }
        skuId = skuDetail.getId();
        RestResponse result = payOrderService.getSingleOrderPayData(token, addrId, proCode, skuId, qty, orderType, groupCode);
        return result;
    }

    /**
     * 多商品支付页面显示
     *
     * @param token   获取cid
     * @param cartids 购物车id集合
     * @return
     */
    @RequestMapping(value = OrderMapping.GET_MORE_ORDER)
    public RestResponse getMoreOrder(String token, @RequestParam(value = "cartIds") List<Integer> cartids, Integer addrId) {
        RestResponse result = payOrderService.getCartOrderPayData(token, addrId, cartids, false, null);
        return result;
    }

    /**
     * 附近商家多商品支付页面显示
     *
     * @param token   获取cid
     * @param cartids 购物车id集合
     * @return
     */
    @RequestMapping(value = OrderMapping.GET_NEARBUSSINESS_MORE_ORDER)
    public RestResponse getNearBusinessMoreOrder(String token, @RequestParam(value = "cartIds") List<Integer> cartids, Integer bid) {
        RestResponse result = payOrderService.getCartOrderPayData(token, null, cartids, true, bid);
        return result;
    }

    //endregion

    //region 订单支付


    /**
     * 处理商城订单支付 （线上、线下）
     *
     * @param token       获取cid
     * @param payCode     支付页面返回token
     * @param payWord     支付密码(余额支付用到)
     * @param payType     支付方式见枚举PayTypeEnums
     * @param remark      订单备注
     * @param payChannel  支付渠道见枚举PayChannlEnums
     * @param fromChannel 来源渠道见枚举LoginChannelEnums
     * @param type        1 单商品订单支付  2 多商品订单支付
     * @return
     * @author
     */
    @RequestMapping(value = OrderMapping.HANDLE_ORDER_PAY)
    public RestResponse handleOrderPay(String token, String payCode, String payWord, Integer payType, String remark,
                                       Integer payChannel, Integer fromChannel, Integer type) {
        RestResponse result = payOrderService.handlePayOrder(payCode, token, payWord, payType, remark, payChannel, fromChannel, type);
        return result;
    }

    /**
     * 处理单笔鸡舍订单订单去支付
     *
     * @param token 获取cid
     * @return
     * @author xiaoky
     */
    @RequestMapping(value = OrderMapping.HANDLE_CHICKEN_ORDER_PAY)
    public RestResponse handleFarmOrderPay(String token, FarmOrderPayVo vo) {
        RestResponse result = payOrderService.handlePayChickenOrder(token, vo);
        return result;
    }

    /**
     * 处理单笔物流提鸡订单去支付
     *
     * @param token 获取cid
     * @return
     * @author xiaoky
     */
    @RequestMapping(value = OrderMapping.HANDLE_CHICKEN_Logistics_ORDER_PAY)
    public RestResponse handleFarmLogisticsOrderPay(String token, FarmLogisticsOrderPayVo vo) {
        RestResponse result = payOrderService.handlePayChickenLogisticsOrder(token, vo);
        return result;
    }

    /**
     * 处理订单重新支付
     *
     * @param token      获取cid
     * @param orderCode  订单编号
     * @param payChannel 支付渠道
     * @return
     * @author xiaoky
     */
    @RequestMapping(value = OrderMapping.HANDLE_ORDER_AGAIN_PAY)
    public RestResponse handleOrderAgainPay(String token, String orderCode, Integer payChannel) {
        RestResponse result = payOrderService.handleAgain(token, orderCode, payChannel);
        return result;
    }


    //endregion

    //region 商城订单退款


    /**
     * 查询退款原因
     *
     * @return
     * @author xiaoky
     */
    @RequestMapping(value = OrderMapping.QUERY_CANCEL_REASON)
    public RestResponse queryCancelReason() {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("reason", "不想买了");
        list.add(map);
        map = new HashMap<String, Object>();
        map.put("reason", "商品无货");
        list.add(map);
        map = new HashMap<String, Object>();
        map.put("reason", "信息填写错误");
        list.add(map);
        map = new HashMap<String, Object>();
        map.put("reason", "其他");
        list.add(map);
        return GetRest.getSuccess("", list);
    }


    /**
     * 查询退款数据
     *
     * @param page  分页
     * @param token 获取cid
     * @return RestResponse 退款数据
     */
    @RequestMapping(value = OrderMapping.QUERY_REFUND_LIST)
    public RestResponse queryRefund(BasePage<RefundVo> page, String token, RefundVo refund) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        refund.setCid(cid);
        IPage<RefundVo> pageInfo = orderRefundLogService.queryRefundList(page, refund);
        return GetRest.getSuccess("", pageInfo);
    }

    /**
     * 查询订单退款详情
     *
     * @param token      获取cid
     * @param refundCode 退款编号
     * @return RestResponse 退款数据
     */
    @RequestMapping(value = OrderMapping.GET_REFUND_DETAIL)
    public RestResponse getRefundDetail(String token, String refundCode) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        RefundVo refund = orderRefundLogService.getRefundDetail(refundCode);
        if (!CalcuUtils.getInstance().isEquals(cid, refund.getCid())) {
            return GetRest.getFail("退款详情查询失败");
        }
        // 店铺联系信息
        BusinessInfoVo businessMsg = apiBusinessService.queryBusinessLinkMsg(refund.getBid());
        refund.setBusinessMsg(businessMsg);
        return GetRest.getSuccess("", refund);
    }

    /**
     * 取消退款接口
     *
     * @param token        获取cid
     * @param refundCode   退款编号
     * @param cancelReason 取消原因
     * @return RestResponse 处理结果
     */
    @RequestMapping(value = OrderMapping.CANCEL_REFUND)
    public RestResponse cancelRefund(String token, String refundCode, String cancelReason) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        RefundVo refund = orderRefundLogService.getRefundDetail(refundCode);
        if (!CalcuUtils.getInstance().isEquals(cid, refund.getCid())) {
            return GetRest.getFail("取消退款失败");
        }
        RestResponse result = orderRefundLogService.cancelRefund(refund.getId(), cancelReason);
        return result;
    }

    /**
     * 订单退款申请数据
     *
     * @param orderDetailId 订单详情id
     * @return
     * @author xiaoky
     */
    @RequestMapping(value = OrderMapping.GET_REFUND_APPLY_PAGE)
    public RestResponse getRefundApplyPage(Integer orderDetailId) {
        RefundVo refundVo = orderRefundLogService.getRefundApplyPage(orderDetailId);
        return GetRest.getSuccess("", refundVo);
    }

    /**
     * 查询退款原因
     *
     * @return
     * @author xiaoky
     */
    @RequestMapping(value = OrderMapping.QUERY_REFUND_REASON)
    public RestResponse queryRefundReason() {
        List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("reason", "七天无理由退款");
        list.add(map);
        map = new HashMap<String, Object>();
        map.put("reason", "不想要了");
        list.add(map);
        map = new HashMap<String, Object>();
        map.put("reason", "商品与描述不符");
        list.add(map);
        map = new HashMap<String, Object>();
        map.put("reason", "其他");
        list.add(map);
        return GetRest.getSuccess("", list);
    }

    /**
     * 处理退款申请
     *
     * @param token     获取cid
     * @param refundLog 申请信息
     * @return
     * @author xiaoky
     */
    @RequestMapping(value = OrderMapping.HANDLE_REFUND_APPLY)
    public RestResponse handleRefundApply(String token, OrderRefundLog refundLog) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        refundLog.setCid(cid);
        RestResponse result = orderRefundLogService.handleRefundApply(refundLog);
        return result;
    }

    /**
     * 退款协商历史
     *
     * @param orderDetailId
     * @return
     * @author xiaoky
     */
    @RequestMapping(value = OrderMapping.QUERY_REFUND_HISTORY)
    public RestResponse queryRefundHistory(Integer orderDetailId) {
        List<OrderRefundLog> list = orderRefundLogService.queryRefundHistory(orderDetailId);
        return GetRest.getSuccess("", list);
    }

    /**
     * 待发货订单直接退款
     *
     * @param token         获取cid
     * @param orderDetailId 订单详情
     * @param reason        退款原因(只是由前端传值过来——未有任何处理)
     * @return
     * @author xiaoky
     */
    @RequestMapping(value = OrderMapping.HANDLE_DIRECT_REFUND)
    public RestResponse handleDirectRefund(String token, Integer orderDetailId, String reason) {
        Integer cid = loginTokenService.validLoginCid(token);
        if (StringUtils.isBlank(token) || cid == null) {
            return GetRest.getFail("获取用户信息失败");
        }
        return orderRefundLogService.handleDirectRefund(cid, orderDetailId, reason);
    }

    //endregion
}
